package com.fanghaoran.notes.MyDataSource;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;

/**
 * @Author: win11
 * @Date: 2023/04/30/0:50
 * @Description: 自定义数据库连接池
 */
public class MyDataSource {
    private final String url;
    private final String username;
    private final String password;
    private final int initialSize;
    private final int maxSize;
    private int currentSize;
    private final List<Connection> pool;

    /**
     * 构造方法
     * @param properties 配置文件
     */
    public MyDataSource(Properties properties) {
        this.url = properties.getProperty("url");
        this.username = properties.getProperty("username");
        this.password = properties.getProperty("password");
        try {
            this.initialSize = Integer.parseInt(properties.getProperty("initialSize","3"));
            this.maxSize = Integer.parseInt(properties.getProperty("maxSize","5"));
        } catch (NumberFormatException e) {
            e.printStackTrace();
            throw new IllegalArgumentException("initialSize or maxSize is invalid");
        }
        this.currentSize = 0;
        this.pool = new ArrayList<>(maxSize);
        initPool();
    }

    /**
     * 初始化连接池
     */
    private void initPool() {
        try {
            for (int i = 0; i < initialSize; i++) {
                Connection connection = getConnection();
                pool.add(connection);
                currentSize++;
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

    /**
     * 获取连接
     * @return 连接对象
     * @throws SQLException 异常
     */
    public synchronized Connection getConnection() throws SQLException {
        if (pool.size() > 0) {
            Connection connection = pool.get(0);
            pool.remove(0);
            return connection;
        }
        if (currentSize < maxSize) {
            Connection connection = DriverManager.getConnection(url, username, password);
            pool.add(connection);
            currentSize++;
            return connection;
        }
        throw new SQLException("Can't get connection from pool");
    }

    /**
     * 归还连接
     * @param connection 连接对象
     * @throws SQLException 异常
     */
    private synchronized void releaseConnection(Connection connection) throws SQLException {
        if (pool.size() < maxSize) {
            pool.add(connection);
        } else {
            connection.close();
        }
    }

    /**
     * 关闭连接池
     */
    public void close() throws SQLException {
        for (Connection connection : pool) {
            connection.close();
        }
    }
}
